import {
  forwardRef,
  lazy,
  useCallback,
  useEffect,
  useImperativeHandle,
  useMemo,
  useRef,
  useState,
} from 'react';
import { getMethod, getTreeList, TreeListData } from './service';
import { useForm } from '@formily/react';

import { Input, Spin, Table, Tree, Checkbox } from 'antd';
import { InbizIcon } from '@inbiz/utils';
import { getMessage } from '@inbiz/react';
import style from './serverModal.less'
const PageComponent = lazy(() => import("@inbiz/setters").then(res => ({default: res.PageComponent.default})))
type DataType = {
  Remark: string;
  MethodName: string;
  Id: string;
  key: string;
  ServerKey: string;
  OutParm: any[];
  MethodKey: string;
  GroupKey?: string;
};

type IPorps = {
  selectDatas: DataType[];
  setSelectedRowKeys: Function;
  selectedRowKeys: string[];
  ref: any;
};

const ServerModal = (props: IPorps, ref: any) => {
  const { selectDatas, selectedRowKeys, setSelectedRowKeys } = props;
  const form = useForm();
  const { appInfo } = form as unknown as { appInfo: { appId: string } };

  const [spinning, setSpinning] = useState<boolean>(true); //左侧加载
  const [listServerData, setListServerData] = useState<TreeListData>(); //左侧数据
  const [selectListKey, setSelectListKey] = useState<{
    key: string;
    random: number;
    groupKey?: string;
  }>(); //左侧选中的KEY
  const [total, setTotal] = useState<number>(0); //分页器total
  const [current, setCurrent] = useState<number>(1); //页数
  const [pageSize, setPageSize] = useState<number>(5); //页容量
  const customPageSizeArr = [5, 10, 15, 20]; //可选页容量
  const [tableSpinning, setTableSpinning] = useState<boolean>(true); //表格加载
  const [tableData, setTableData] = useState<any[]>(); //表格数据
  const [searchValue, setSearchValue] = useState<string>(); //搜索的值
  const [selectData, setSelectData] = useState<DataType[]>(selectDatas || []);
  const [defaultExpandedKeys, $defaultExpandedKeys] = useState<
    undefined | string[]
  >();
  const isContaisInnerGroupRef = useRef(true);
  const [isContaisInnerGroup, $isContaisInnerGroup] = useState(true);
  //表格数据
  const columns = [
    {
      title: getMessage('ApiQuery.apiName'),
      dataIndex: 'MethodName',
      key: 'MethodName',
      width: 240,
      ellipsis: true,
      render: (value: string) => {
        return <span title={value?.length > 14 ? value : ''}>{value}</span>;
      },
    },
    {
      title: getMessage('ApiQuery.remark'),
      dataIndex: 'Remark',
      key: 'Remark',
      width: 270,
      ellipsis: true,
      render: (value: string) => {
        return <span title={value?.length > 18 ? value : ''}>{value}</span>;
      },
    },
  ];

  useEffect(() => {
    getTreeList({ appId: appInfo.appId, lowestLevel: '1' }).then((res) => {
      setSpinning(false);
      setListServerData(res);
      const { ServerKey, GroupKey } = props.selectDatas?.[0] || {};
      setSelectListKey({
        key: ServerKey || res[0].Id,
        random: Math.random(),
        groupKey: ServerKey || res[0].Id || '',
      });
      if (GroupKey) {
        const expandedKeys = findTreeParents({
          keyValue: GroupKey,
          key: 'Id',
          treeData: res,
          childrenKey: 'Children',
        })?.map((item: { Id: any }) => item.Id);
        if (expandedKeys?.length) {
          $defaultExpandedKeys(expandedKeys);
          return;
        }
      }
      $defaultExpandedKeys([]);
    });
  }, []);

  useImperativeHandle(
    ref,
    () => {
      return { selectData, setSelectData };
    },
    [selectData],
  );

  useEffect(() => {
    if (selectDatas?.length) {
      setSelectData(selectDatas);
    }
  }, [selectDatas]);

  const handleSelect = useCallback(
    (selectedKeys, e) => {
      if (e.selected) {
        setSelectListKey({
          key: e.node.ServerKey || selectedKeys[0],
          groupKey: selectedKeys[0],
          random: Math.random(),
        });
      }
    },
    [listServerData],
  );

  useEffect(() => {
    if (selectListKey?.key) {
      setCurrent(1);
      setSearchValue('');
    }
  }, [selectListKey]);

  const tryString = (value: string) => {
    if (value) {
      try {
        return JSON.parse(value?.replace(/\n/g, ''));
      } catch {
        return eval('(' + value + ')');
      }
    } else {
      return value;
    }
  };

  useEffect(() => {
    if (selectListKey) {
      setTableSpinning(true);
      let groupKey =
        selectListKey.key === selectListKey.groupKey
          ? undefined
          : selectListKey.groupKey;
      if (groupKey?.includes('_')) {
        groupKey = groupKey.split('_')[1];
      }
      getMethod({
        appId: appInfo.appId,
        serverKey: selectListKey.key,
        maxResultCount: pageSize,
        skipCount: (current - 1) * pageSize,
        groupKey,
        isContaisInnerGroup: isContaisInnerGroupRef.current,
      }).then((res) => {
        setTableData(
          res?.Items?.map((item) => {
            return {
              MethodName: item.MethodName,
              Remark: item.Remark,
              key: item.MethodKey,
              ServerKey: item.ServerKey,
              OutParm: tryString(item.OutParm),
              MethodKey: item.MethodKey,
              GroupKey: selectListKey.groupKey,
            };
          }),
        );
        setTableSpinning(false);
        setTotal(res?.TotalCount);
      });
    } else {
      setTableSpinning(false);
    }
  }, [selectListKey]);

  const onSelectRow = (record: DataType, selected: any) => {
    let oldSelectData = [...selectData];

    if (selected) {
      oldSelectData.push(record);
    }

    if (oldSelectData.length > 1) {
      oldSelectData = [oldSelectData[oldSelectData.length - 1]];
    }

    setSelectData(oldSelectData);
    setSelectedRowKeys(oldSelectData.map((v) => v.key));
  };

  const selectRow = (record: DataType) => {
    let selectedRowKey = [...selectedRowKeys];

    if (!(selectedRowKey.indexOf(record.key) > -1)) {
      selectedRowKey.push(record.key);
    }

    let oldSelectData = [...selectData];
    let num = oldSelectData.findIndex((item) => item.key === record.key);

    if (!(num > -1)) {
      oldSelectData.push(record);
    }

    if (selectedRowKey.length > 1) {
      oldSelectData = [oldSelectData[oldSelectData.length - 1]];
      selectedRowKey = [selectedRowKey[selectedRowKey.length - 1]];
    }

    setSelectData(oldSelectData);
    setSelectedRowKeys(selectedRowKey);
  };

  const rowSelection = {
    selectedRowKeys,
    hideSelectAll: false,
    onSelect: onSelectRow,
    type: 'radio',
  };

  useEffect(() => {
    if (selectListKey) {
      setTableSpinning(true);
      getMethod({
        appId: appInfo.appId,
        serverKey: selectListKey!.key,
        maxResultCount: pageSize,
        skipCount: (current - 1) * pageSize,
        contain: searchValue,
        isContaisInnerGroup: isContaisInnerGroupRef.current,
      }).then((res) => {
        setTableData(
          res?.Items?.map((item) => {
            return {
              MethodName: item.MethodName,
              Remark: item.Remark,
              key: item.MethodKey,
              ServerKey: item.ServerKey,
              OutParm: tryString(item.OutParm),
              MethodKey: item.MethodKey,
              GroupKey: selectListKey.groupKey,
            };
          }),
        );

        setTableSpinning(false);
        setTotal(res?.TotalCount);
      });
    }
  }, [current, pageSize]);

  const onSearch = (value: string) => {
    if (value) {
      let groupKey = selectListKey?.groupKey;
      if (groupKey?.includes('_')) {
        groupKey = groupKey.split('_')[1];
      }
      if (groupKey === selectListKey?.key) {
        groupKey = '';
      }
      setCurrent(1);
      setSearchValue(value);
      setTableSpinning(true);
      getMethod({
        appId: appInfo.appId,
        serverKey: selectListKey!.key,
        maxResultCount: pageSize,
        skipCount: (current - 1) * pageSize,
        contain: searchValue,
        isContaisInnerGroup: isContaisInnerGroupRef.current,
        groupKey,
      }).then((res) => {
        setTableData(
          res?.Items?.map((item) => {
            return {
              MethodName: item.MethodName,
              Remark: item.Remark,
              key: item.MethodKey,
              ServerKey: item.ServerKey,
              OutParm: tryString(item.OutParm),
              MethodKey: item.MethodKey,
              GroupKey: selectListKey!.groupKey,
            };
          }),
        );
        setTableSpinning(false);
        setTotal(res?.TotalCount);
      });
    } else {
      setSearchValue('');
      setTableSpinning(true);
      getMethod({
        appId: appInfo.appId,
        serverKey: selectListKey!.key,
        maxResultCount: pageSize,
        skipCount: (current - 1) * pageSize,
        isContaisInnerGroup: isContaisInnerGroupRef.current,
      }).then((res) => {
        setTableData(
          res?.Items?.map((item) => {
            return {
              MethodName: item.MethodName,
              Remark: item.Remark,
              key: item.MethodKey,
              ServerKey: item.ServerKey,
              OutParm: tryString(item.OutParm),
              MethodKey: item.MethodKey,
              GroupKey: selectListKey!.groupKey,
            };
          }),
        );
        setTableSpinning(false);
        setTotal(res?.TotalCount);
      });
    }
  };

  const suffix = useMemo(
    () => (
      <span onClick={() => onSearch(searchValue || '')}>
        <InbizIcon
          type={'icon-ic-sousuo'}
          style={{ color: '#999', fontSize: 16, cursor: 'pointer' }}
        />
      </span>
    ),
    [searchValue],
  );

  return (
    <div className={style.serverModal}>
      <div className="serverModalContent">
        <div className="serverContentLeft">
          <div className="serverLeftBox">
            {spinning ? (
              <Spin spinning={spinning} className="leftSpin" size="large" />
            ) : null}
            {defaultExpandedKeys && (
              <Tree
                //@ts-ignore
                treeData={listServerData}
                fieldNames={{ key: 'Id', title: 'Name', children: 'Children' }}
                blockNode
                selectedKeys={
                  selectListKey?.groupKey ? [selectListKey.groupKey] : undefined
                }
                onSelect={handleSelect}
                defaultExpandedKeys={defaultExpandedKeys}
              />
            )}
          </div>
        </div>
        <div className="serverContentRight">
          <Input
            className="rightSearch"
            placeholder={getMessage('ApiQuery.queryCriteria')}
            value={searchValue}
            onChange={(e: any) => {
              setSearchValue(e.target.value);
            }}
            suffix={suffix}
            onPressEnter={() => {
              onSearch(searchValue || '');
            }}
          />
          <Checkbox
            className="contaisCheckbox"
            checked={isContaisInnerGroup}
            onChange={(e) => {
              isContaisInnerGroupRef.current = e.target.checked;
              $isContaisInnerGroup(e.target.checked);
            }}
          >
            包含子分组
          </Checkbox>
          <Table
            className="rightTable"
            bordered
            columns={columns}
            loading={tableSpinning}
            dataSource={tableData}
            pagination={false}
            onRow={(record: any) => ({
              onClick: () => {
                selectRow(record);
              },
            })}
            rowSelection={rowSelection}
          />
          <PageComponent
            total={total}
            current={current}
            pageSize={pageSize}
            setCurrent={setCurrent}
            setPageSize={setPageSize}
            customPageSizeArr={customPageSizeArr}
          />
        </div>
      </div>
    </div>
  );
};

export default forwardRef(ServerModal);

export type { DataType };

// 查找节点的所有父级节点
export function findTreeParents(props: {
  key?: string;
  keyValue: string;
  treeData?: any;
  resultSelf?: boolean;
  result?: any;
  childrenKey?: string;
}) {
  if (!props.treeData?.length) {
    return [];
  }
  const result = props.result || [];
  const key = props.key || 'key';
  if (props.treeData?.length) {
    const data = props.treeData.find((item) => item[key] == props.keyValue);
    if (!data) {
      let parentNodes;
      const childrenKey = props.childrenKey || 'children';
      const isfind = props.treeData.some((item) => {
        if (item[childrenKey]) {
          parentNodes = findTreeParents({
            ...props,
            //@ts-ignore
            treeData: item[childrenKey],
            result: result.concat(item),
          });
          return !!parentNodes?.length;
        } else {
          return false;
        }
      });
      if (isfind) {
        return parentNodes;
      } else {
        return [];
      }
    } else {
      return props.resultSelf ? result.concat(data) : result;
    }
  } else {
    return [];
  }
}
